/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package controller.commands;

import core.DispatcherPort;
import core.InPort;
import core.Node;
import core.OutPort;
import core.TriggerPort;
import core.TriggerTransmitterNode;
import core.ValueTransmitterNode;
import javax.swing.JLayeredPane;
import javax.swing.JOptionPane;
import model.graphic.objects.GBoxNode;
import model.graphic.objects.GHandleConnection;
import model.graphic.objects.GTriggerConnection;
import model.graphic.objects.GTrigger;
import model.graphic.objects.GDispatcherPort;
import model.graphic.objects.GInputPort;
import model.graphic.objects.GNode;
import model.graphic.objects.GOutput;
import model.graphic.objects.GOutputPort;
import model.graphic.objects.GTriggerPort;
import model.graphic.objects.Graphical;
import model.graphic.objects.RectangleGraphical;
import view.GUI.LabelReader;

/**
 *
 * @author Jelle
 */
public class AddConnectionCommand extends BasicCommand {

    private GOutput output;
    private GInputPort input;
    private GTrigger trigger;
    private GDispatcherPort dispatcherport;
    private Graphical toDelete;
    private int modus = 0;
    private JLayeredPane pane;

    public AddConnectionCommand(GDispatcherPort dispatcherport, GTrigger trigger, Graphical toDelete, JLayeredPane pane) {
        this.dispatcherport = dispatcherport;
        this.trigger = trigger;
        this.toDelete = toDelete;
        this.modus = 1;
        this.pane = pane;
    }

    public AddConnectionCommand(GInputPort input, GOutput output, Graphical toDelete, JLayeredPane pane) {
        this.output = output;
        this.input = input;
        this.toDelete = toDelete;
        this.modus = 2;
        this.pane = pane;
    }

    public AddConnectionCommand(GDispatcherPort dispatcherport, GTrigger trigger) {
        this.dispatcherport = dispatcherport;
        this.trigger = trigger;
        this.modus = 1;
    }

    public AddConnectionCommand(GOutput output, GInputPort input) {
        this.output = output;
        this.input = input;
        this.modus = 2;
    }


    @Override
    public void execute() {
        

        if (modus == 1) {
            GNode gn1 = null, gn2 = null;
            GTriggerConnection tc = null;
            try {
                tc = new GTriggerConnection(dispatcherport, trigger);
                RectangleGraphical g1 = (RectangleGraphical) dispatcherport.getBase();
                RectangleGraphical g2 = (RectangleGraphical) ((GTriggerPort) trigger.getBase()).getBase();
                boolean inbox = false;
                GBoxNode bn = null;
                if (GNode.class.isAssignableFrom(g1.getClass())) {
                    gn1 = (GNode) g1;
                    gn1.addConnectionToNode(tc);
                    if (gn1.isBoxed()) {
                        inbox = true;
                        bn = gn1.getBoxNode();
                    }
                }
                if (GNode.class.isAssignableFrom(g2.getClass())) {
                    gn2 = (GNode) g2;
                    gn2.addConnectionToNode(tc);
                    if (gn2.isBoxed()) {
                        inbox = true;
                        bn = gn2.getBoxNode();
                    }
                }

                Node n1 = sync.get(g1);
                Node n2 = sync.get(g2);

                if (TriggerTransmitterNode.class.isAssignableFrom(n2.getClass()) && TriggerTransmitterNode.class.isAssignableFrom(n1.getClass())) {
                        TriggerTransmitterNode t1 = (TriggerTransmitterNode) n1;
                        t1.getDispatcherPort().addTarget(((TriggerTransmitterNode)n2).getTriggerPort());
                        sync.put(((TriggerTransmitterNode)n2).getTriggerPort(), tc);
                        if (inbox) {
                            bn.addInternalObject(tc);
                        } else {
                            gmodel.addObject(tc);
                        }
                        gview.add(tc);
                        gview.setLayer(tc, 10, 0);
                }else if (Node.class.isAssignableFrom(n2.getClass()) && TriggerTransmitterNode.class.isAssignableFrom(n1.getClass())) {
                  //  try {
                        TriggerTransmitterNode t1 = (TriggerTransmitterNode) n1;
                        t1.getDispatcherPort().addTarget((TriggerPort)n2.getPort(trigger.getBase().getName()));
                        sync.put((TriggerPort)n2.getPort(trigger.getBase().getName()), tc);
                        if (inbox) {
                            bn.addInternalObject(tc);
                        } else {
                            gmodel.addObject(tc);
                        }
                        gview.add(tc);
                        gview.setLayer(tc, 10, 0);
                   /* } catch (ConnectException ex) {
                        showPopup("AddConnectionCommand:" + ex.getMessage(), LabelReader.getInstance().getString("Error"), JOptionPane.ERROR_MESSAGE);
                    }*/
                } else if (TriggerTransmitterNode.class.isAssignableFrom(n2.getClass()) && Node.class.isAssignableFrom(n1.getClass())) {
                  //  try {
                        TriggerTransmitterNode t2 = (TriggerTransmitterNode) n2;
                        ((DispatcherPort) n1.getPort(dispatcherport.getName())).addTarget((TriggerPort) t2.getTriggerPort());
                        sync.put((TriggerPort) t2.getTriggerPort(), tc);
                        if (inbox) {
                            bn.addInternalObject(tc);
                        } else {
                            gmodel.addObject(tc);
                        }
                        gview.add(tc);
                        gview.setLayer(tc, 10, 0);
                   /* } catch (ConnectException ex) {
                        showPopup("AddConnectionCommand:" + ex.getMessage(), LabelReader.getInstance().getString("Error"), JOptionPane.ERROR_MESSAGE);
                    }*/
                } else if (Node.class.isAssignableFrom(n2.getClass()) && Node.class.isAssignableFrom(n1.getClass())) {
                    //try {
                        ((DispatcherPort) n1.getPort(dispatcherport.getName())).addTarget((TriggerPort) n2.getPort(trigger.getBase().getName()));
                        sync.put((TriggerPort) n2.getPort(trigger.getBase().getName()), tc);
                        if (inbox) {
                            bn.addInternalObject(tc);
                        } else {
                            gmodel.addObject(tc);
                        }
                        gview.add(tc);
                        gview.setLayer(tc, 10, 0);
                  /*  } catch (ConnectException ex) {
                        showPopup("AddConnectionCommand:" + ex.getMessage(), LabelReader.getInstance().getString("Error"), JOptionPane.ERROR_MESSAGE);
                        
                    }*/
                }
                //gmodel.setSelected(dispatcherport);

            } catch (Exception ex) {
                if(gn1 != null){ 
                    gn1.removeConnectionToNode(tc); 
                }
                if(gn2 != null){
                    gn2.removeConnectionToNode(tc);
                }
                 showPopup("AddConnectionCommand:" + ex.getMessage(), LabelReader.getInstance().getString("Error"), JOptionPane.ERROR_MESSAGE);
                System.out.println(LabelReader.getInstance().getString("EXCEPTIONAddConnectionCommand") + ex.getMessage());
                ex.printStackTrace();
            }
        } else if (modus == 2) {
            GHandleConnection tc = null;
            GNode gn1 = null ,gn2 = null;
            try {
                tc = new GHandleConnection(output, input);
                RectangleGraphical g = (RectangleGraphical) ((GOutputPort) output.getBase()).getBase();
                RectangleGraphical g2 = (RectangleGraphical) input.getBase();
                boolean inbox = false;
                GBoxNode bn = null;
                if (GNode.class.isAssignableFrom(g.getClass())) {
                    gn1 = (GNode) g;
                    gn1.addConnectionToNode(tc);
                    if (gn1.isBoxed()) {
                        inbox = true;
                        bn = gn1.getBoxNode();
                    }
                }
                if (GNode.class.isAssignableFrom(g2.getClass())) {
                    gn2 = (GNode) g2;
                    gn2.addConnectionToNode(tc);
                    if (gn2.isBoxed()) {
                        inbox = true;
                        bn = gn2.getBoxNode();
                    }
                }

                Node n1 = sync.get(g);
                Node n2 = sync.get(g2);

                if (ValueTransmitterNode.class.isAssignableFrom(n2.getClass()) && ValueTransmitterNode.class.isAssignableFrom(n1.getClass())){
                        ValueTransmitterNode t1 = (ValueTransmitterNode) n1;
                        ValueTransmitterNode t2 = (ValueTransmitterNode) n2;
                        (t2.getInPort()).setSource(t1.getOutPort());
                        sync.put(t2.getInPort(), tc);
                        if (inbox) {
                            bn.addInternalObject(tc);
                        } else {
                            gmodel.addObject(tc);
                        }
                        gview.add(tc);
                        gview.setLayer(tc, 10, 0);
                        if(toDelete != null){
                            gmodel.removeDefObject(toDelete);
                        }
                }else if (Node.class.isAssignableFrom(n2.getClass()) && ValueTransmitterNode.class.isAssignableFrom(n1.getClass())) {
                   // try {
                        ValueTransmitterNode t1 = (ValueTransmitterNode) n1;
                        ((InPort) n2.getPort(input.getName())).setSource((OutPort) t1.getOutPort());
                        sync.put(((InPort) n2.getPort(input.getName())), tc);
                        if (inbox) {
                            bn.addInternalObject(tc);
                        } else {
                            gmodel.addObject(tc);
                        }
                        gview.add(tc);
                        gview.setLayer(tc, 10, 0);
                        if(toDelete != null){
                            gmodel.removeDefObject(toDelete);
                        }
                  /*  } catch (ConnectException ex) {
                        showPopup("AddConnectionCommand:" + ex.getMessage(), LabelReader.getInstance().getString("Error"), JOptionPane.ERROR_MESSAGE);
                        //gview.notifyObservers(new AddAttachmentCommand(Constants.getInputString(), input));
                    }*/
                } else if (ValueTransmitterNode.class.isAssignableFrom(n2.getClass()) && Node.class.isAssignableFrom(n1.getClass())) {
                   // try {
                        ValueTransmitterNode t2 = (ValueTransmitterNode) n2;
                        ((InPort) t2.getInPort()).setSource((OutPort) n1.getPort(((GOutputPort) output.getBase()).getName()));
                        sync.put(((InPort) t2.getInPort()), tc);
                        if (inbox) {
                            bn.addInternalObject(tc);
                        } else {
                            gmodel.addObject(tc);

                        }
                        gview.add(tc);
                        gview.setLayer(tc, 10, 0);
                        if(toDelete != null){
                            gmodel.removeDefObject(toDelete);
                        }
                  /*  } catch (ConnectException ex) {
                        showPopup("AddConnectionCommand:" + ex.getMessage(), LabelReader.getInstance().getString("Error"), JOptionPane.ERROR_MESSAGE);
                     //   gview.notifyObservers(new AddAttachmentCommand(Constants.getInputString(), input));
                    }*/
                } else if (Node.class.isAssignableFrom(n2.getClass()) && Node.class.isAssignableFrom(n1.getClass())) {
                  //  try {
                        ((InPort) n2.getPort(input.getName())).setSource((OutPort) n1.getPort(((GOutputPort) output.getBase()).getName()));
                        sync.put(((InPort) n2.getPort(input.getName())), tc);
                        if (inbox) {
                            bn.addInternalObject(tc);
                        } else {
                            gmodel.addObject(tc);

                        }
                        gview.add(tc);
                        gview.setLayer(tc, 10, 0);
                        if(toDelete != null){
                            gmodel.removeDefObject(toDelete);
                        }
                   /* } catch (ConnectException ex) {
                        showPopup("AddConnectionCommand:" + ex.getMessage(), LabelReader.getInstance().getString("Error"), JOptionPane.ERROR_MESSAGE);
                      //  gview.notifyObservers(new AddAttachmentCommand(Constants.getInputString(), input));
                    }*/
                }

                controller.getDebug().append(LabelReader.getInstance().getString("ConnectionBetweenTypes") + tc.getOutput().getType() + LabelReader.getInstance().getString("And") + tc.getInput().getType()+".\n");

            } catch (Exception ex) {
                if(gn1 != null){
                    gn1.removeConnectionToNode(tc);
                }
                if(gn2 != null){
                    gn2.removeConnectionToNode(tc);
                }
                showPopup("AddConnectionCommand:" + ex.getMessage(), LabelReader.getInstance().getString("Error"), JOptionPane.ERROR_MESSAGE);
                System.out.println(LabelReader.getInstance().getString("EXCEPTIONAddConnectionCommand") + " 2 " + ex.getMessage());
                ex.printStackTrace();
            }
        } 
        System.out.println(LabelReader.getInstance().getString("AddConnectionCommandExecuted"));
    }
}